home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume9 / uemacs3.8b / patch1 < prev    next >
Encoding:
Internet Message Format  |  1987-04-13  |  25.7 KB

  1. Subject:  v09i047:  Repost of display.c from MicroEmacs, Patch1
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.TMC.COM
  4.  
  5. Submitted by: pur-ee!pur-phy!duncan!lawrence
  6. Mod.sources: Volume 9, Issue 47
  7. Archive-name: uemacs3.8b/Patch1
  8.  
  9. [  When last we heard from this group, articles had been leaving
  10.    site "mirror" with 512 bytes elided from them...  This is the
  11.    first of a couple of re-posts.  --r$  ]
  12.  
  13. Daniel Lawrence can be reached at:
  14.     UUCP:    ihnp4!pur-ee!pur-phy!duncan!lawrence
  15.     ARPA:    nwd@j.cc.purdue.edu
  16.     FIDO:    The Programmer's Room 201/2
  17.         (317) 742-5533  300/1200 baud  24 hours
  18.     USmail:    617 New York St
  19.         Lafayette, IN 47901
  20.     ATT:    (317) 742-5153
  21. -----CUT-----HERE-----
  22. #! /bin/sh
  23. # This is a shell archive.  Remove anything before this line,
  24. # then unpack it by saving it in a file and typing "sh file".
  25. # If this archive is complete, you will see the message:
  26. #        "End of shell archive."
  27. # Contents:  display.c
  28. # Wrapped by rs@mirror on Tue Apr 14 16:52:46 1987
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. echo shar: Extracting \"display.c\" \(23829 characters\)
  31. if test -f display.c ; then 
  32.   echo shar: Will not over-write existing file \"display.c\"
  33. else
  34. sed "s/^X//" >display.c <<'END_OF_display.c'
  35. X/*
  36. X * The functions in this file handle redisplay. There are two halves, the
  37. X * ones that update the virtual display screen, and the ones that make the
  38. X * physical display screen the same as the virtual display screen. These
  39. X * functions use hints that are left in the windows by the commands.
  40. X *
  41. X */
  42. X
  43. X#include        <stdio.h>
  44. X#include    "estruct.h"
  45. X#include        "edef.h"
  46. X
  47. X#if    MEGAMAX & ST520
  48. Xoverlay    "display"
  49. X#endif
  50. X
  51. Xtypedef struct  VIDEO {
  52. X        int    v_flag;                 /* Flags */
  53. X#if    COLOR
  54. X    int    v_fcolor;        /* current forground color */
  55. X    int    v_bcolor;        /* current background color */
  56. X    int    v_rfcolor;        /* requested forground color */
  57. X    int    v_rbcolor;        /* requested background color */
  58. X#endif
  59. X        char    v_text[1];              /* Screen data. */
  60. X}       VIDEO;
  61. X
  62. X#define VFCHG   0x0001                  /* Changed flag            */
  63. X#define    VFEXT    0x0002            /* extended (beyond column 80)    */
  64. X#define    VFREV    0x0004            /* reverse video status        */
  65. X#define    VFREQ    0x0008            /* reverse video request    */
  66. X#define    VFCOL    0x0010            /* color change requested    */
  67. X
  68. XVIDEO   **vscreen;                      /* Virtual screen. */
  69. X#if    MEMMAP == 0
  70. XVIDEO   **pscreen;                      /* Physical screen. */
  71. X#endif
  72. X
  73. X/*
  74. X * Initialize the data structures used by the display code. The edge vectors
  75. X * used to access the screens are set up. The operating system's terminal I/O
  76. X * channel is set up. All the other things get initialized at compile time.
  77. X * The original window has "WFCHG" set, so that it will get completely
  78. X * redrawn on the first call to "update".
  79. X */
  80. Xvtinit()
  81. X{
  82. X    register int i;
  83. X    register VIDEO *vp;
  84. X    char *malloc();
  85. X
  86. X    TTopen();        /* open the screen */
  87. X    TTkopen();        /* open the keyboard */
  88. X    TTrev(FALSE);
  89. X    vscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
  90. X
  91. X    if (vscreen == NULL)
  92. X        exit(1);
  93. X
  94. X#if    MEMMAP == 0
  95. X    pscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
  96. X
  97. X    if (pscreen == NULL)
  98. X        exit(1);
  99. X#endif
  100. X
  101. X    for (i = 0; i < term.t_nrow; ++i)
  102. X        {
  103. X        vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol);
  104. X
  105. X        if (vp == NULL)
  106. X            exit(1);
  107. X
  108. X    vp->v_flag = 0;
  109. X#if    COLOR
  110. X    vp->v_rfcolor = 7;
  111. X    vp->v_rbcolor = 0;
  112. X#endif
  113. X        vscreen[i] = vp;
  114. X#if    MEMMAP == 0
  115. X        vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol);
  116. X
  117. X        if (vp == NULL)
  118. X            exit(1);
  119. X
  120. X    vp->v_flag = 0;
  121. X        pscreen[i] = vp;
  122. X#endif
  123. X        }
  124. X}
  125. X
  126. X/*
  127. X * Clean up the virtual terminal system, in anticipation for a return to the
  128. X * operating system. Move down to the last line and clear it out (the next
  129. X * system prompt will be written in the line). Shut down the channel to the
  130. X * terminal.
  131. X */
  132. Xvttidy()
  133. X{
  134. X    mlerase();
  135. X    movecursor(term.t_nrow, 0);
  136. X    TTflush();
  137. X    TTclose();
  138. X    TTkclose();
  139. X}
  140. X
  141. X/*
  142. X * Set the virtual cursor to the specified row and column on the virtual
  143. X * screen. There is no checking for nonsense values; this might be a good
  144. X * idea during the early stages.
  145. X */
  146. Xvtmove(row, col)
  147. X{
  148. X    vtrow = row;
  149. X    vtcol = col;
  150. X}
  151. X
  152. X/* Write a character to the virtual screen. The virtual row and
  153. X   column are updated. If we are not yet on left edge, don't print
  154. X   it yet. If the line is too long put a "$" in the last column.
  155. X   This routine only puts printing characters into the virtual
  156. X   terminal buffers. Only column overflow is checked.
  157. X*/
  158. X
  159. Xvtputc(c)
  160. X
  161. Xint c;
  162. X
  163. X{
  164. X    register VIDEO *vp;    /* ptr to line being updated */
  165. X
  166. X    vp = vscreen[vtrow];
  167. X
  168. X    if (c == '\t') {
  169. X        do {
  170. X            vtputc(' ');
  171. X        } while (((vtcol + taboff)&0x07) != 0);
  172. X    } else if (vtcol >= term.t_ncol) {
  173. X        ++vtcol;
  174. X        vp->v_text[term.t_ncol - 1] = '$';
  175. X    } else if (c < 0x20 || c == 0x7F) {
  176. X        vtputc('^');
  177. X        vtputc(c ^ 0x40);
  178. X    } else {
  179. X        if (vtcol >= 0)
  180. X            vp->v_text[vtcol] = c;
  181. X        ++vtcol;
  182. X    }
  183. X}
  184. X
  185. X/*
  186. X * Erase from the end of the software cursor to the end of the line on which
  187. X * the software cursor is located.
  188. X */
  189. Xvteeol()
  190. X{
  191. X    register VIDEO      *vp;
  192. X
  193. X    vp = vscreen[vtrow];
  194. X    while (vtcol < term.t_ncol)
  195. X        vp->v_text[vtcol++] = ' ';
  196. X}
  197. X
  198. X/* upscreen:    user routine to force a screen update
  199. X        always finishes complete update        */
  200. X
  201. Xupscreen(f, n)
  202. X
  203. X{
  204. X    update(TRUE);
  205. X    return(TRUE);
  206. X}
  207. X
  208. X/*
  209. X * Make sure that the display is right. This is a three part process. First,
  210. X * scan through all of the windows looking for dirty ones. Check the framing,
  211. X * and refresh the screen. Second, make sure that "currow" and "curcol" are
  212. X * correct for the current window. Third, make the virtual and physical
  213. X * screens the same.
  214. X */
  215. Xupdate(force)
  216. X
  217. Xint force;    /* force update past type ahead? */
  218. X
  219. X{
  220. X    register WINDOW *wp;
  221. X
  222. X#if    TYPEAH
  223. X    if (force == FALSE && typahead())
  224. X        return(TRUE);
  225. X#endif
  226. X#if    VISMAC == 0
  227. X    if (force == FALSE && kbdmode == PLAY)
  228. X        return(TRUE);
  229. X#endif
  230. X
  231. X    /* update any windows that need refreshing */
  232. X    wp = wheadp;
  233. X    while (wp != NULL) {
  234. X        if (wp->w_flag) {
  235. X            /* if the window has changed, service it */
  236. X            reframe(wp);    /* check the framing */
  237. X            if ((wp->w_flag & ~WFMODE) == WFEDIT)
  238. X                updone(wp);    /* update EDITed line */
  239. X            else if (wp->w_flag & ~WFMOVE)
  240. X                updall(wp);    /* update all lines */
  241. X            if (wp->w_flag & WFMODE)
  242. X                modeline(wp);    /* update modeline */
  243. X            wp->w_flag = 0;
  244. X            wp->w_force = 0;
  245. X        }
  246. X        /* on to the next window */
  247. X        wp = wp->w_wndp;
  248. X    }
  249. X
  250. X    /* recalc the current hardware cursor location */
  251. X    updpos();
  252. X
  253. X#if    MEMMAP
  254. X    /* update the cursor and flush the buffers */
  255. X    movecursor(currow, curcol - lbound);
  256. X#endif
  257. X
  258. X    /* check for lines to de-extend */
  259. X    upddex();
  260. X
  261. X    /* if screen is garbage, re-plot it */
  262. X    if (sgarbf != FALSE)
  263. X        updgar();
  264. X
  265. X    /* update the virtual screen to the physical screen */
  266. X    updupd(force);
  267. X
  268. X    /* update the cursor and flush the buffers */
  269. X    movecursor(currow, curcol - lbound);
  270. X    TTflush();
  271. X    return(TRUE);
  272. X}
  273. X
  274. X/*    reframe:    check to see if the cursor is on in the window
  275. X            and re-frame it if needed or wanted        */
  276. X
  277. Xreframe(wp)
  278. X
  279. XWINDOW *wp;
  280. X
  281. X{
  282. X    register LINE *lp;
  283. X    register int i;
  284. X
  285. X    /* if not a requested reframe, check for a needed one */
  286. X    if ((wp->w_flag & WFFORCE) == 0) {
  287. X        lp = wp->w_linep;
  288. X        for (i = 0; i < wp->w_ntrows; i++) {
  289. X
  290. X            /* if the line is in the window, no reframe */
  291. X            if (lp == wp->w_dotp)
  292. X                return(TRUE);
  293. X
  294. X            /* if we are at the end of the file, reframe */
  295. X            if (lp == wp->w_bufp->b_linep)
  296. X                break;
  297. X
  298. X            /* on to the next line */
  299. X            lp = lforw(lp);
  300. X        }
  301. X    }
  302. X
  303. X    /* reaching here, we need a window refresh */
  304. X    i = wp->w_force;
  305. X
  306. X    /* how far back to reframe? */
  307. X    if (i > 0) {        /* only one screen worth of lines max */
  308. X        if (--i >= wp->w_ntrows)
  309. X            i = wp->w_ntrows - 1;
  310. X    } else if (i < 0) {    /* negative update???? */
  311. X        i += wp->w_ntrows;
  312. X        if (i < 0)
  313. X            i = 0;
  314. X    } else
  315. X        i = wp->w_ntrows / 2;
  316. X
  317. X    /* backup to new line at top of window */
  318. X    lp = wp->w_dotp;
  319. X    while (i != 0 && lback(lp) != wp->w_bufp->b_linep) {
  320. X        --i;
  321. X        lp = lback(lp);
  322. X    }
  323. X
  324. X    /* and reset the current line at top of window */
  325. X    wp->w_linep = lp;
  326. X    wp->w_flag |= WFHARD;
  327. X    wp->w_flag &= ~WFFORCE;
  328. X    return(TRUE);
  329. X}
  330. X
  331. X/*    updone:    update the current line    to the virtual screen        */
  332. X
  333. Xupdone(wp)
  334. X
  335. XWINDOW *wp;    /* window to update current line in */
  336. X
  337. X{
  338. X    register LINE *lp;    /* line to update */
  339. X    register int sline;    /* physical screen line to update */
  340. X    register int i;
  341. X
  342. X    /* search down the line we want */
  343. X    lp = wp->w_linep;
  344. X    sline = wp->w_toprow;
  345. X    while (lp != wp->w_dotp) {
  346. X        ++sline;
  347. X        lp = lforw(lp);
  348. X    }
  349. X
  350. X    /* and update the virtual line */
  351. X    vscreen[sline]->v_flag |= VFCHG;
  352. X    vscreen[sline]->v_flag &= ~VFREQ;
  353. X    vtmove(sline, 0);
  354. X    for (i=0; i < llength(lp); ++i)
  355. X        vtputc(lgetc(lp, i));
  356. X#if    COLOR
  357. X    vscreen[sline]->v_rfcolor = wp->w_fcolor;
  358. X    vscreen[sline]->v_rbcolor = wp->w_bcolor;
  359. X#endif
  360. X    vteeol();
  361. X}
  362. X
  363. X/*    updall:    update all the lines in a window on the virtual screen */
  364. X
  365. Xupdall(wp)
  366. X
  367. XWINDOW *wp;    /* window to update lines in */
  368. X
  369. X{
  370. X    register LINE *lp;    /* line to update */
  371. X    register int sline;    /* physical screen line to update */
  372. X    register int i;
  373. X
  374. X    /* search down the lines, updating them */
  375. X    lp = wp->w_linep;
  376. X    sline = wp->w_toprow;
  377. X    while (sline < wp->w_toprow + wp->w_ntrows) {
  378. X
  379. X        /* and update the virtual line */
  380. X        vscreen[sline]->v_flag |= VFCHG;
  381. X        vscreen[sline]->v_flag &= ~VFREQ;
  382. X        vtmove(sline, 0);
  383. X        if (lp != wp->w_bufp->b_linep) {
  384. X            /* if we are not at the end */
  385. X            for (i=0; i < llength(lp); ++i)
  386. X                vtputc(lgetc(lp, i));
  387. X            lp = lforw(lp);
  388. X        }
  389. X
  390. X        /* on to the next one */
  391. X#if    COLOR
  392. X        vscreen[sline]->v_rfcolor = wp->w_fcolor;
  393. X        vscreen[sline]->v_rbcolor = wp->w_bcolor;
  394. X#endif
  395. X        vteeol();
  396. X        ++sline;
  397. X    }
  398. X
  399. X}
  400. X
  401. X/*    updpos:    update the position of the hardware cursor and handle extended
  402. X        lines. This is the only update for simple moves.    */
  403. X
  404. Xupdpos()
  405. X
  406. X{
  407. X    register LINE *lp;
  408. X    register int c;
  409. X    register int i;
  410. X
  411. X    /* find the current row */
  412. X    lp = curwp->w_linep;
  413. X    currow = curwp->w_toprow;
  414. X    while (lp != curwp->w_dotp) {
  415. X        ++currow;
  416. X        lp = lforw(lp);
  417. X    }
  418. X
  419. X    /* find the current column */
  420. X    curcol = 0;
  421. X    i = 0;
  422. X    while (i < curwp->w_doto) {
  423. X        c = lgetc(lp, i++);
  424. X        if (c == '\t')
  425. X            curcol |= 0x07;
  426. X        else
  427. X            if (c < 0x20 || c == 0x7f)
  428. X                ++curcol;
  429. X
  430. X        ++curcol;
  431. X    }
  432. X
  433. X    /* if extended, flag so and update the virtual line image */
  434. X    if (curcol >=  term.t_ncol - 1) {
  435. X        vscreen[currow]->v_flag |= (VFEXT | VFCHG);
  436. X        updext();
  437. X    } else
  438. X        lbound = 0;
  439. X}
  440. X
  441. X/*    upddex:    de-extend any line that derserves it        */
  442. X
  443. Xupddex()
  444. X
  445. X{
  446. X    register WINDOW *wp;
  447. X    register LINE *lp;
  448. X    register int i,j;
  449. X
  450. X    wp = wheadp;
  451. X
  452. X    while (wp != NULL) {
  453. X        lp = wp->w_linep;
  454. X        i = wp->w_toprow;
  455. X
  456. X        while (i < wp->w_toprow + wp->w_ntrows) {
  457. X            if (vscreen[i]->v_flag & VFEXT) {
  458. X                if ((wp != curwp) || (lp != wp->w_dotp) ||
  459. X                   (curcol < term.t_ncol - 1)) {
  460. X                    vtmove(i, 0);
  461. X                    for (j = 0; j < llength(lp); ++j)
  462. X                        vtputc(lgetc(lp, j));
  463. X                    vteeol();
  464. X
  465. X                    /* this line no longer is extended */
  466. X                    vscreen[i]->v_flag &= ~VFEXT;
  467. X                    vscreen[i]->v_flag |= VFCHG;
  468. X                }
  469. X            }
  470. X            lp = lforw(lp);
  471. X            ++i;
  472. X        }
  473. X        /* and onward to the next window */
  474. X        wp = wp->w_wndp;
  475. X    }
  476. X}
  477. X
  478. X/*    updgar:    if the screen is garbage, clear the physical screen and
  479. X        the virtual screen and force a full update        */
  480. X
  481. Xupdgar()
  482. X
  483. X{
  484. X    register char *txt;
  485. X    register int i,j;
  486. X
  487. X    for (i = 0; i < term.t_nrow; ++i) {
  488. X        vscreen[i]->v_flag |= VFCHG;
  489. X#if    REVSTA
  490. X        vscreen[i]->v_flag &= ~VFREV;
  491. X#endif
  492. X#if    COLOR
  493. X        vscreen[i]->v_fcolor = gfcolor;
  494. X        vscreen[i]->v_bcolor = gbcolor;
  495. X#endif
  496. X#if    MEMMAP == 0
  497. X        txt = pscreen[i]->v_text;
  498. X        for (j = 0; j < term.t_ncol; ++j)
  499. X            txt[j] = ' ';
  500. X#endif
  501. X    }
  502. X
  503. X    movecursor(0, 0);         /* Erase the screen. */
  504. X    (*term.t_eeop)();
  505. X    sgarbf = FALSE;             /* Erase-page clears */
  506. X    mpresf = FALSE;             /* the message area. */
  507. X#if    COLOR
  508. X    mlerase();            /* needs to be cleared if colored */
  509. X#endif
  510. X}
  511. X
  512. X/*    updupd:    update the physical screen from the virtual screen    */
  513. X
  514. Xupdupd(force)
  515. X
  516. Xint force;    /* forced update flag */
  517. X
  518. X{
  519. X    register VIDEO *vp1;
  520. X    register int i;
  521. X
  522. X    for (i = 0; i < term.t_nrow; ++i) {
  523. X        vp1 = vscreen[i];
  524. X
  525. X        /* for each line that needs to be updated*/
  526. X        if ((vp1->v_flag & VFCHG) != 0) {
  527. X#if    TYPEAH
  528. X            if (force == FALSE && typahead())
  529. X                return(TRUE);
  530. X#endif
  531. X#if    MEMMAP
  532. X            updateline(i, vp1);
  533. X#else
  534. X            updateline(i, vp1, pscreen[i]);
  535. X#endif
  536. X        }
  537. X    }
  538. X    return(TRUE);
  539. X}
  540. X
  541. X/*    updext: update the extended line which the cursor is currently
  542. X        on at a column greater than the terminal width. The line
  543. X        will be scrolled right or left to let the user see where
  544. X        the cursor is
  545. X                                */
  546. X
  547. Xupdext()
  548. X
  549. X{
  550. X    register int rcursor;    /* real cursor location */
  551. X    register LINE *lp;    /* pointer to current line */
  552. X    register int j;        /* index into line */
  553. X
  554. X    /* calculate what column the real cursor will end up in */
  555. X    rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin;
  556. X    taboff = lbound = curcol - rcursor + 1;
  557. X
  558. X    /* scan through the line outputing characters to the virtual screen */
  559. X    /* once we reach the left edge                    */
  560. X    vtmove(currow, -lbound);    /* start scanning offscreen */
  561. X    lp = curwp->w_dotp;        /* line to output */
  562. X    for (j=0; j<llength(lp); ++j)    /* until the end-of-line */
  563. X        vtputc(lgetc(lp, j));
  564. X
  565. X    /* truncate the virtual line, restore tab offset */
  566. X    vteeol();
  567. X    taboff = 0;
  568. X
  569. X    /* and put a '$' in column 1 */
  570. X    vscreen[currow]->v_text[0] = '$';
  571. X}
  572. X
  573. X/*
  574. X * Update a single line. This does not know how to use insert or delete
  575. X * character sequences; we are using VT52 functionality. Update the physical
  576. X * row and column variables. It does try an exploit erase to end of line. The
  577. X * RAINBOW version of this routine uses fast video.
  578. X */
  579. X#if    MEMMAP
  580. X/*    UPDATELINE specific code for the IBM-PC and other compatables */
  581. X
  582. Xupdateline(row, vp1)
  583. X
  584. Xint row;        /* row of screen to update */
  585. Xstruct VIDEO *vp1;    /* virtual screen image */
  586. X
  587. X{
  588. X#if    COLOR
  589. X    scwrite(row, vp1->v_text, vp1->v_rfcolor, vp1->v_rbcolor);
  590. X    vp1->v_fcolor = vp1->v_rfcolor;
  591. X    vp1->v_bcolor = vp1->v_rbcolor;
  592. X#else
  593. X    if (vp1->v_flag & VFREQ)
  594. X        scwrite(row, vp1->v_text, 0, 7);
  595. X    else
  596. X        scwrite(row, vp1->v_text, 7, 0);
  597. X#endif
  598. X    vp1->v_flag &= ~(VFCHG | VFCOL);    /* flag this line as changed */
  599. X
  600. X}
  601. X
  602. X#else
  603. X
  604. Xupdateline(row, vp1, vp2)
  605. X
  606. Xint row;        /* row of screen to update */
  607. Xstruct VIDEO *vp1;    /* virtual screen image */
  608. Xstruct VIDEO *vp2;    /* physical screen image */
  609. X
  610. X{
  611. X#if RAINBOW
  612. X/*    UPDATELINE specific code for the DEC rainbow 100 micro    */
  613. X
  614. X    register char *cp1;
  615. X    register char *cp2;
  616. X    register int nch;
  617. X
  618. X    /* since we don't know how to make the rainbow do this, turn it off */
  619. X    flags &= (~VFREV & ~VFREQ);
  620. X
  621. X    cp1 = &vp1->v_text[0];                    /* Use fast video. */
  622. X    cp2 = &vp2->v_text[0];
  623. X    putline(row+1, 1, cp1);
  624. X    nch = term.t_ncol;
  625. X
  626. X    do
  627. X        {
  628. X        *cp2 = *cp1;
  629. X        ++cp2;
  630. X        ++cp1;
  631. X        }
  632. X    while (--nch);
  633. X    *flags &= ~VFCHG;
  634. X#else
  635. X/*    UPDATELINE code for all other versions        */
  636. X
  637. X    register char *cp1;
  638. X    register char *cp2;
  639. X    register char *cp3;
  640. X    register char *cp4;
  641. X    register char *cp5;
  642. X    register int nbflag;    /* non-blanks to the right flag? */
  643. X    int rev;        /* reverse video flag */
  644. X    int req;        /* reverse video request flag */
  645. X
  646. X
  647. X    /* set up pointers to virtual and physical lines */
  648. X    cp1 = &vp1->v_text[0];
  649. X    cp2 = &vp2->v_text[0];
  650. X
  651. X#if    COLOR
  652. X    TTforg(vp1->v_rfcolor);
  653. X    TTbacg(vp1->v_rbcolor);
  654. X#endif
  655. X
  656. X#if    REVSTA | COLOR
  657. X    /* if we need to change the reverse video status of the
  658. X       current line, we need to re-write the entire line     */
  659. X    rev = (vp1->v_flag & VFREV) == VFREV;
  660. X    req = (vp1->v_flag & VFREQ) == VFREQ;
  661. X    if ((rev != req)
  662. X#if    COLOR
  663. X        || (vp1->v_fcolor != vp1->v_rfcolor) || (vp1->v_bcolor != vp1->v_rbcolor)
  664. X#endif
  665. X#if    HP150
  666. X    /* the HP150 has some reverse video problems */
  667. X        || req || rev
  668. X#endif
  669. X            ) {
  670. X        movecursor(row, 0);    /* Go to start of line. */
  671. X        /* set rev video if needed */
  672. X        if (rev != req)
  673. X            (*term.t_rev)(req);
  674. X
  675. X        /* scan through the line and dump it to the screen and
  676. X           the virtual screen array                */
  677. X        cp3 = &vp1->v_text[term.t_ncol];
  678. X        while (cp1 < cp3) {
  679. X            TTputc(*cp1);
  680. X            ++ttcol;
  681. X            *cp2++ = *cp1++;
  682. X        }
  683. X        /* turn rev video off */
  684. X        if (rev != req)
  685. X            (*term.t_rev)(FALSE);
  686. X
  687. X        /* update the needed flags */
  688. X        vp1->v_flag &= ~VFCHG;
  689. X        if (req)
  690. X            vp1->v_flag |= VFREV;
  691. X        else
  692. X            vp1->v_flag &= ~VFREV;
  693. X#if    COLOR
  694. X        vp1->v_fcolor = vp1->v_rfcolor;
  695. X        vp1->v_bcolor = vp1->v_rbcolor;
  696. X#endif
  697. X        return(TRUE);
  698. X    }
  699. X#endif
  700. X
  701. X    /* advance past any common chars at the left */
  702. X    while (cp1 != &vp1->v_text[term.t_ncol] && cp1[0] == cp2[0]) {
  703. X        ++cp1;
  704. X        ++cp2;
  705. X    }
  706. X
  707. X/* This can still happen, even though we only call this routine on changed
  708. X * lines. A hard update is always done when a line splits, a massive
  709. X * change is done, or a buffer is displayed twice. This optimizes out most
  710. X * of the excess updating. A lot of computes are used, but these tend to
  711. X * be hard operations that do a lot of update, so I don't really care.
  712. X */
  713. X    /* if both lines are the same, no update needs to be done */
  714. X    if (cp1 == &vp1->v_text[term.t_ncol]) {
  715. X         vp1->v_flag &= ~VFCHG;        /* flag this line is changed */
  716. X        return(TRUE);
  717. X    }
  718. X
  719. X    /* find out if there is a match on the right */
  720. X    nbflag = FALSE;
  721. X    cp3 = &vp1->v_text[term.t_ncol];
  722. X    cp4 = &vp2->v_text[term.t_ncol];
  723. X
  724. X    while (cp3[-1] == cp4[-1]) {
  725. X        --cp3;
  726. X        --cp4;
  727. X        if (cp3[0] != ' ')        /* Note if any nonblank */
  728. X            nbflag = TRUE;        /* in right match. */
  729. X    }
  730. X
  731. X    cp5 = cp3;
  732. X
  733. X    /* Erase to EOL ? */
  734. X    if (nbflag == FALSE && eolexist == TRUE && (req != TRUE)) {
  735. X        while (cp5!=cp1 && cp5[-1]==' ')
  736. X            --cp5;
  737. X
  738. X        if (cp3-cp5 <= 3)        /* Use only if erase is */
  739. X            cp5 = cp3;        /* fewer characters. */
  740. X    }
  741. X
  742. X    movecursor(row, cp1 - &vp1->v_text[0]);    /* Go to start of line. */
  743. X#if    REVSTA
  744. X    TTrev(rev);
  745. X#endif
  746. X
  747. X    while (cp1 != cp5) {        /* Ordinary. */
  748. X        TTputc(*cp1);
  749. X        ++ttcol;
  750. X        *cp2++ = *cp1++;
  751. X    }
  752. X
  753. X    if (cp5 != cp3) {        /* Erase. */
  754. X        TTeeol();
  755. X        while (cp1 != cp3)
  756. X            *cp2++ = *cp1++;
  757. X    }
  758. X#if    REVSTA
  759. X    TTrev(FALSE);
  760. X#endif
  761. X    vp1->v_flag &= ~VFCHG;        /* flag this line as updated */
  762. X    return(TRUE);
  763. X#endif
  764. X}
  765. X#endif
  766. X
  767. X/*
  768. X * Redisplay the mode line for the window pointed to by the "wp". This is the
  769. X * only routine that has any idea of how the modeline is formatted. You can
  770. X * change the modeline format by hacking at this routine. Called by "update"
  771. X * any time there is a dirty window.
  772. X */
  773. Xmodeline(wp)
  774. X    WINDOW *wp;
  775. X{
  776. X    register char *cp;
  777. X    register int c;
  778. X    register int n;        /* cursor position count */
  779. X    register BUFFER *bp;
  780. X    register i;            /* loop index */
  781. X    register lchar;        /* character to draw line in buffer with */
  782. X    register firstm;        /* is this the first mode? */
  783. X    char tline[NLINE];        /* buffer for part of mode line */
  784. X
  785. X    n = wp->w_toprow+wp->w_ntrows;          /* Location. */
  786. X    vscreen[n]->v_flag |= VFCHG | VFREQ | VFCOL;/* Redraw next time. */
  787. X#if    COLOR
  788. X    vscreen[n]->v_rfcolor = 0;            /* black on */
  789. X    vscreen[n]->v_rbcolor = 7;            /* white.....*/
  790. X#endif
  791. X    vtmove(n, 0);                           /* Seek to right line. */
  792. X    if (wp == curwp)                /* mark the current buffer */
  793. X    lchar = '=';
  794. X    else
  795. X#if    REVSTA
  796. X    if (revexist)
  797. X        lchar = ' ';
  798. X    else
  799. X#endif
  800. X        lchar = '-';
  801. X
  802. X    vtputc(lchar);
  803. X    bp = wp->w_bufp;
  804. X
  805. X    if ((bp->b_flag&BFCHG) != 0)                /* "*" if changed. */
  806. X        vtputc('*');
  807. X    else
  808. X        vtputc(lchar);
  809. X
  810. X    n  = 2;
  811. X    strcpy(tline, " MicroEMACS ");        /* Buffer name. */
  812. X    strcat(tline, VERSION);
  813. X    strcat(tline, " (");
  814. X
  815. X    /* display the modes */
  816. X
  817. X    firstm = TRUE;
  818. X    for (i = 0; i < NUMMODES; i++)    /* add in the mode flags */
  819. X        if (wp->w_bufp->b_mode & (1 << i)) {
  820. X            if (firstm != TRUE)
  821. X                strcat(tline, " ");
  822. X            firstm = FALSE;
  823. X            strcat(tline, modename[i]);
  824. X        }
  825. X    strcat(tline,") ");
  826. X
  827. X    cp = &tline[0];
  828. X    while ((c = *cp++) != 0)
  829. X        {
  830. X        vtputc(c);
  831. X        ++n;
  832. X        }
  833. X
  834. X#if 0
  835. X    vtputc(lchar);
  836. X    vtputc((wp->w_flag&WFCOLR) != 0  ? 'C' : lchar);
  837. X    vtputc((wp->w_flag&WFMODE) != 0  ? 'M' : lchar);
  838. X    vtputc((wp->w_flag&WFHARD) != 0  ? 'H' : lchar);
  839. X    vtputc((wp->w_flag&WFEDIT) != 0  ? 'E' : lchar);
  840. X    vtputc((wp->w_flag&WFMOVE) != 0  ? 'V' : lchar);
  841. X    vtputc((wp->w_flag&WFFORCE) != 0 ? 'F' : lchar);
  842. X    vtputc(lchar);
  843. X    n += 8;
  844. X#endif
  845. X
  846. X    vtputc(lchar);
  847. X    vtputc(lchar);
  848. X    vtputc(' ');
  849. X    n += 3;
  850. X    cp = &bp->b_bname[0];
  851. X
  852. X    while ((c = *cp++) != 0)
  853. X        {
  854. X        vtputc(c);
  855. X        ++n;
  856. X        }
  857. X
  858. X    vtputc(' ');
  859. X    vtputc(lchar);
  860. X    vtputc(lchar);
  861. X    n += 3;
  862. X
  863. X    if (bp->b_fname[0] != 0)            /* File name. */
  864. X        {
  865. X    vtputc(' ');
  866. X    ++n;
  867. X        cp = "File: ";
  868. X
  869. X        while ((c = *cp++) != 0)
  870. X            {
  871. X            vtputc(c);
  872. X            ++n;
  873. X            }
  874. X
  875. X        cp = &bp->b_fname[0];
  876. X
  877. X        while ((c = *cp++) != 0)
  878. X            {
  879. X            vtputc(c);
  880. X            ++n;
  881. X            }
  882. X
  883. X        vtputc(' ');
  884. X        ++n;
  885. X        }
  886. X
  887. X    while (n < term.t_ncol)             /* Pad to full width. */
  888. X        {
  889. X        vtputc(lchar);
  890. X        ++n;
  891. X        }
  892. X}
  893. X
  894. Xupmode()    /* update all the mode lines */
  895. X
  896. X{
  897. X    register WINDOW *wp;
  898. X
  899. X    wp = wheadp;
  900. X    while (wp != NULL) {
  901. X        wp->w_flag |= WFMODE;
  902. X        wp = wp->w_wndp;
  903. X    }
  904. X}
  905. X
  906. X/*
  907. X * Send a command to the terminal to move the hardware cursor to row "row"
  908. X * and column "col". The row and column arguments are origin 0. Optimize out
  909. X * random calls. Update "ttrow" and "ttcol".
  910. X */
  911. Xmovecursor(row, col)
  912. X    {
  913. X    if (row!=ttrow || col!=ttcol)
  914. X        {
  915. X        ttrow = row;
  916. X        ttcol = col;
  917. X        TTmove(row, col);
  918. X        }
  919. X    }
  920. X
  921. X/*
  922. X * Erase the message line. This is a special routine because the message line
  923. X * is not considered to be part of the virtual screen. It always works
  924. X * immediately; the terminal buffer is flushed via a call to the flusher.
  925. X */
  926. Xmlerase()
  927. X    {
  928. X    int i;
  929. X    
  930. X    movecursor(term.t_nrow, 0);
  931. X#if    COLOR
  932. X     TTforg(7);
  933. X     TTbacg(0);
  934. X#endif
  935. X    if (eolexist == TRUE)
  936. X        TTeeol();
  937. X    else {
  938. X        for (i = 0; i < term.t_ncol - 1; i++)
  939. X            TTputc(' ');
  940. X        movecursor(term.t_nrow, 1);    /* force the move! */
  941. X        movecursor(term.t_nrow, 0);
  942. X    }
  943. X    TTflush();
  944. X    mpresf = FALSE;
  945. X    }
  946. X
  947. X/*
  948. X * Write a message into the message line. Keep track of the physical cursor
  949. X * position. A small class of printf like format items is handled. Assumes the
  950. X * stack grows down; this assumption is made by the "++" in the argument scan
  951. X * loop. Set the "message line" flag TRUE.
  952. X */
  953. X
  954. Xmlwrite(fmt, arg)
  955. X    char *fmt;
  956. X    {
  957. X    register int c;
  958. X    register char *ap;
  959. X
  960. X#if    COLOR
  961. X    TTforg(7);
  962. X    TTbacg(0);
  963. X#endif
  964. X    if (eolexist == FALSE) {
  965. X        mlerase();
  966. X        TTflush();
  967. X    }
  968. X
  969. X    movecursor(term.t_nrow, 0);
  970. X    ap = (char *) &arg;
  971. X    while ((c = *fmt++) != 0) {
  972. X        if (c != '%') {
  973. X            TTputc(c);
  974. X            ++ttcol;
  975. X            }
  976. X        else
  977. X            {
  978. X            c = *fmt++;
  979. X            switch (c) {
  980. X                case 'd':
  981. X                    mlputi(*(int *)ap, 10);
  982. X                    ap += sizeof(int);
  983. X                    break;
  984. X
  985. X                case 'o':
  986. X                    mlputi(*(int *)ap,  8);
  987. X                    ap += sizeof(int);
  988. X                    break;
  989. X
  990. X                case 'x':
  991. X                    mlputi(*(int *)ap, 16);
  992. X                    ap += sizeof(int);
  993. X                    break;
  994. X
  995. X                case 'D':
  996. X                    mlputli(*(long *)ap, 10);
  997. X                    ap += sizeof(long);
  998. X                    break;
  999. X
  1000. X                case 's':
  1001. X                    mlputs(*(char **)ap);
  1002. X                    ap += sizeof(char *);
  1003. X                    break;
  1004. X
  1005. X        case 'f':
  1006. X            mlputf(*(int *)ap);
  1007. X            ap += sizeof(int);
  1008. X            break;
  1009. X
  1010. X                default:
  1011. X                    TTputc(c);
  1012. X                    ++ttcol;
  1013. X                }
  1014. X            }
  1015. X        }
  1016. X    if (eolexist == TRUE)
  1017. X        TTeeol();
  1018. X    TTflush();
  1019. X    mpresf = TRUE;
  1020. X    }
  1021. X
  1022. X/*
  1023. X * Write out a string. Update the physical cursor position. This assumes that
  1024. X * the characters in the string all have width "1"; if this is not the case
  1025. X * things will get screwed up a little.
  1026. X */
  1027. Xmlputs(s)
  1028. X    char *s;
  1029. X    {
  1030. X    register int c;
  1031. X
  1032. X    while ((c = *s++) != 0)
  1033. X        {
  1034. X        TTputc(c);
  1035. X        ++ttcol;
  1036. X        }
  1037. X    }
  1038. X
  1039. X/*
  1040. X * Write out an integer, in the specified radix. Update the physical cursor
  1041. X * position.
  1042. X */
  1043. Xmlputi(i, r)
  1044. X    {
  1045. X    register int q;
  1046. X    static char hexdigits[] = "0123456789ABCDEF";
  1047. X
  1048. X    if (i < 0)
  1049. X        {
  1050. X        i = -i;
  1051. X        TTputc('-');
  1052. X        }
  1053. X
  1054. X    q = i/r;
  1055. X
  1056. X    if (q != 0)
  1057. X        mlputi(q, r);
  1058. X
  1059. X    TTputc(hexdigits[i%r]);
  1060. X    ++ttcol;
  1061. X    }
  1062. X
  1063. X/*
  1064. X * do the same except as a long integer.
  1065. X */
  1066. Xmlputli(l, r)
  1067. X    long l;
  1068. X    {
  1069. X    register long q;
  1070. X
  1071. X    if (l < 0)
  1072. X        {
  1073. X        l = -l;
  1074. X        TTputc('-');
  1075. X        }
  1076. X
  1077. X    q = l/r;
  1078. X
  1079. X    if (q != 0)
  1080. X        mlputli(q, r);
  1081. X
  1082. X    TTputc((int)(l%r)+'0');
  1083. X    ++ttcol;
  1084. X    }
  1085. X
  1086. X/*
  1087. X *    write out a scaled integer with two decimal places
  1088. X */
  1089. X
  1090. Xmlputf(s)
  1091. X
  1092. Xint s;    /* scaled integer to output */
  1093. X
  1094. X{
  1095. X    int i;    /* integer portion of number */
  1096. X    int f;    /* fractional portion of number */
  1097. X
  1098. X    /* break it up */
  1099. X    i = s / 100;
  1100. X    f = s % 100;
  1101. X
  1102. X    /* send out the integer portion */
  1103. X    mlputi(i, 10);
  1104. X    TTputc('.');
  1105. X    TTputc((f / 10) + '0');
  1106. X    TTputc((f % 10) + '0');
  1107. X    ttcol += 3;
  1108. X}    
  1109. X
  1110. X#if RAINBOW
  1111. X
  1112. Xputline(row, col, buf)
  1113. X    int row, col;
  1114. X    char buf[];
  1115. X    {
  1116. X    int n;
  1117. X
  1118. X    n = strlen(buf);
  1119. X    if (col + n - 1 > term.t_ncol)
  1120. X        n = term.t_ncol - col + 1;
  1121. X    Put_Data(row, col, n, buf);
  1122. X    }
  1123. X#endif
  1124. X
  1125. END_OF_display.c
  1126. if test 23829 -ne `wc -c <display.c`; then
  1127.     echo shar: \"display.c\" unpacked with wrong size!?
  1128. fi
  1129. # end of overwriting check
  1130. fi
  1131. echo shar: End of shell archive.
  1132. exit 0
  1133.